package com.jplus.core.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jplus.core.core.proxys.Proxy;
import com.jplus.core.core.proxys.ProxyChain;
import com.jplus.core.mvc.vo.ModelAndView;

/**
 * 【核心插件】请求拦截<br>
 * 基于插件, 自定义拦截器请 继承改类
 */
public abstract class HandlerInterceptorAdapter implements Proxy {

	@Override
	public final Object doProxy(ProxyChain proxyChain) throws Throwable {
		if (WebContext.getInstance() != null) {
			HttpServletRequest request = WebContext.getRequest();
			HttpServletResponse response = WebContext.getResponse();
			Object handler = proxyChain.getProxyObject();
			Object result = null;
			Exception exp = null;
			try {
				if (preHandle(request, response, handler)) {
					result = proxyChain.doProxyChain();
					if (result instanceof ModelAndView)
						postHandle(request, response, handler, (ModelAndView) result);
					else
						postHandle(request, response, handler, null);
					beforeBodyWrite(response, result);
				}
			} catch (Exception e) {
				exp = e;
			} finally {
				afterCompletion(request, response, handler, exp);
			}
			return result;
		} else {
			return proxyChain.doProxyChain();
		}
	}

	// ================================================
	/**
	 * preHandle：预处理回调方法，实现处理器的预处理（如登录检查），第三个参数为响应的处理器（ Controller实现）；<br>
	 * 返回值：true表示继续流程（如调用下一个拦截器或处理器）；<br>
	 * false表示流程中断（如登录检查失败），不会继续调用其他的拦截器或处理器，此时我们需要通过response来产生响应；<br>
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		return true;
	};

	/**
	 * postHandle：后处理回调方法，实现处理器的后处理（但在渲染视图之前），此时我们可以通过modelAndView（模型和视图对象）<br>
	 * 对模型数据进行处理或对视图进行处理，modelAndView也可能为null。<br>
	 */
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {

	};

	/**
	 * afterCompletion：整个请求处理完毕回调方法，即在视图渲染完毕时回调，<br>
	 * 如性能监控中我们可以在此记录结束时间并输出消耗时间，还可以进行一些资源清理，类似于try-catch-finally中的finally，<br>
	 * 但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。<br>
	 */
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		if (ex != null)
			throw ex;
	}

	/**
	 * 处理返回值
	 */
	public void beforeBodyWrite(HttpServletResponse response, Object body) {
		// TODO something
	}
}
